using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using Jonathan.SharpDB;
using System.Text;
using System.Windows.Forms;

namespace Jonathan
{
	/// <summary>
	/// Class with static methods and fields.
	/// </summary>
    public class Common
    {
        /// <summary>
        /// Bible Table in a bible Database.
        /// </summary>
		public const string TABLE_BIBLES = "Bibles";

		/// <summary>
		/// Info table in a Jonathan Database.
		/// </summary>
		public const string TABLE_INFO = "Info";

		/// <summary>
		/// List table in a Jonathan Database.
		/// </summary>
		public const string TABLE_LIST = "List";

		/// <summary>
		/// Notes table in a Jonathan Database.
		/// </summary>
		public const string TABLE_NOTES = "Notes";

		/// <summary>
		/// Book List table in a Jonathan Database.
		/// </summary>
		public const string TABLE_BOOK_LIST = "BookList";

		/// <summary>
		/// Name of Jonathan's Help File.
		/// </summary>
		public const string HELP_FILE = "jonathan-help.chm";

		/// <summary>
		/// Application data XML file.
		/// </summary>
		public const string FILE_PROGRAM_DATA = "jData.xml";

		/// <summary>
		/// Database used to store verse notes.
		/// </summary>
		public const string DATABASE_VERSE_NOTES = "verseNotes.db";

		/// <summary>
		/// Preface string.
		/// </summary>
		public const string PREFACE = "Preface";

		/// <summary>
		/// Path to Folder where all data is stored.
		/// </summary>
		public static string DATA_FOLDER = System.Windows.Forms.Application.StartupPath + "\\" + "data\\";

		/// <summary>
		/// Database Type Bible.
		/// </summary>
		public const string TYPE_BIBLE = "Bible";

		/// <summary>
		/// Database Type Other Text.
		/// </summary>
		public const string TYPE_OTHER = "Other";

		/// <summary>
		/// Search Type Passage.
		/// </summary>
		public const string TYPE_PASSAGE = "Passage";

		/// <summary>
		/// Database Type Reference
		/// </summary>
		public const string TYPE_REFERENCE = "Reference";

		/// <summary>
		/// Database Type Daily (daily devotionaly).
		/// </summary>
		public const string TYPE_DAILY = "Daily";

		/// <summary>
		/// Name of Book Name Column in the Book List Table.
		/// </summary>
		public const string BOOK_NAME = "BookName";

		/// <summary>
		/// Abbreviation column name.
		/// </summary>
		public const string ABBREVIATION = "Abbreviation";

		/// <summary>
		/// Current Version of Jonathan.
		/// </summary>
		public const string JONATHAN_VERSION = "1.3";

		/// <summary>
		/// Enumeration to define how we are going to perform the search...
		/// </summary>
        public enum SearchCriteria
        {
			/// <summary>
			/// Search for all words in search text, but not in order.
			/// </summary>
            AllWords,
			/// <summary>
			/// Search for any of the words in the search text.
			/// </summary>
            AnyWord,
			/// <summary>
			/// Search for the exact phrase of the search text.
			/// </summary>
            Phrase
        }

		/// <summary>
		/// Creates a path for a round rectangle...
		/// </summary>
		/// <param name="r">Original Rectangle.</param>
		/// <param name="r1">Corner 1 radius.</param>
		/// <param name="r2">Corner 2 radius.</param>
		/// <param name="r3">Corner 3 radius.</param>
		/// <param name="r4">Corner 4 radius.</param>
		/// <returns>GraphicsPath of Round Rectangle.</returns>
        public static GraphicsPath RoundRect(RectangleF r, float r1, float r2, float r3, float r4)
        {
            float x = r.X, y = r.Y, w = r.Width, h = r.Height;
            GraphicsPath rr = new GraphicsPath();
            rr.AddBezier(x, y + r1, x, y, x + r1, y, x + r1, y);
            rr.AddLine(x + r1, y, x + w - r2, y);
            rr.AddBezier(x + w - r2, y, x + w, y, x + w, y + r2, x + w, y + r2);
            rr.AddLine(x + w, y + r2, x + w, y + h - r3);
            rr.AddBezier(x + w, y + h - r3, x + w, y + h, x + w - r3, y + h, x + w - r3, y + h);
            rr.AddLine(x + w - r3, y + h, x + r4, y + h);
            rr.AddBezier(x + r4, y + h, x, y + h, x, y + h - r4, x, y + h - r4);
            rr.AddLine(x, y + h - r4, x, y + r1);
            return rr;
        }

        /// <summary>
        /// Returns if a string is numeric or not...
        /// </summary>
        /// <param name="val">String to test.</param>
        /// <returns>True if numeric, else false.</returns>
        public static bool isNumeric (string val)
        {
            Double result;
            return Double.TryParse(val, System.Globalization.NumberStyles.Integer,
                System.Globalization.CultureInfo.CurrentCulture, out result);
        }

        /// <summary>
        /// Removes the HTML from the string...
        /// </summary>
        /// <param name="oldString">String with HTML.</param>
        /// <returns>String without HTML.</returns>
        public static string RemoveHtml (string oldString)
        {
            string newString = "";
            bool read = true;
            for (int a = 0; a < oldString.Length; a++)
            {
                if (oldString[a] == '<')
                {
                    read = false;
                }
                else if (oldString[a] == '>')
                {
                    read = true;
                }
                else if (read)
                {
                    newString += oldString[a];
                }
            }
            return newString;
        }

        /// <summary>
        /// Gets the text to place inside of a tooltip...
        /// </summary>
        /// <param name="passages">Passage List</param>
        /// <param name="source">Passage Source</param>
        /// <param name="db">Database</param>
        /// <returns>String Builder</returns>
        public static StringBuilder GetToolTipText (List<cPassage> passages, string source, Database db)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<table>");

            foreach (cPassage passage in passages)
            {
                Query q = new Query(QueryType.SELECT, passage.Book);
                q.SELECT("*");
                q.WHERE("Chapter", Operator.EQUALS, passage.Chapter);
                if (passage.Verse != null)
                    q.WHERE("Verse", Operator.EQUALS, passage.Verse);

                db.RunQuery(q);
                string book = cParser.GetBook(passage.Book, false);
                if (string.IsNullOrEmpty(book))
                {
					if (string.IsNullOrEmpty(book))
					{
						string[] spBook = passage.Book.Split(' ');
						foreach (string b in spBook)
						{
							if (Char.IsLetter(b[0]))
								book += b[0].ToString().ToUpper();
						}
					}
                }

                for (int a = 0; a < q.RowsReturned; a++)
                {
                    string pass = book + " " + q.Results.GetFieldString(0, a) + ":" + q.Results.GetFieldString(1, a);
					sb.Append("<tr passage=\"" + book + "|" + q.Results.GetFieldString(0, a) + "|" + q.Results.GetFieldString(1, a) + "\">");
					sb.Append("<td align=\"left\" valign=\"top\"><a class=\"goto\" href=\"" + source + "\" title=\"Goto " + passage.Book + " " + 
						q.Results.GetFieldString(0, a) + ":" + q.Results.GetFieldString(1, a) + "\">");
                    sb.Append(pass);
                    sb.Append("</a></td>");
                    sb.Append("<td align=\"left\" valign=\"top\">");
                    sb.Append(q.Results.GetFieldString(2, a));
                    sb.Append("</td>");
                    sb.Append("</tr>");
                    if (!string.IsNullOrEmpty(q.Results.GetFieldString(4, a)))
                    {
                        sb.Append("<tr><td align=\"left\" valign=\"top\">&nbsp;</td>");
                        sb.Append("<td align=\"center\" valign=\"top\">");
                        sb.Append(q.Results.GetFieldString(4, a));
                        sb.Append("</td></tr>");
                    }
                }
            }
            sb.Append("<tr><td align=\"right\" colspan=\"2\">Source | " + source + "</td></tr>");
            sb.Append("</table>");
            return sb;
        }

        /// <summary>
        ///  Highlight All occurances of the given text.
        /// </summary>
		/// <param name="orgHTML">The HTML code.</param>
        /// <param name="text">Text to highlight.</param>
        /// <param name="caseSensitive">Is the highlighted text case sensitive</param>
        public static string HighlightHTML (string orgHTML, string text, bool caseSensitive)
        {
            if (!orgHTML.StartsWith("<"))
                orgHTML = "<html>" + orgHTML;

            StringBuilder html = new StringBuilder();
            string tempHtml = (caseSensitive) ? orgHTML : orgHTML.ToLower();
            if (!caseSensitive)
                text = text.ToLower();

            int start = 0;
            int lastFind = 0;
            while ((start = tempHtml.IndexOf(text, start)) != -1)
            {
                // Check to see if we are inside any tags...
                for (int a = start; a >= 0; a--)
                {
                    if (orgHTML[a] == '>')
                    {
                        html.Append(orgHTML.Substring(lastFind, start - lastFind));
                        html.Append("<span style=\"background: yellow;\">");
                        html.Append(orgHTML.Substring(start, text.Length));
                        html.Append("</span>");
                        break;
                    }
                    else if (orgHTML[a] == '<')
                    {
                        html.Append(orgHTML.Substring(lastFind, start - lastFind));
                        html.Append(orgHTML.Substring(start, text.Length));
                        break;
                    }
                }
                start += text.Length;
                lastFind = start;
            }

            html.Append(orgHTML.Substring(lastFind, orgHTML.Length - lastFind));
            return html.ToString();
        }

		/// <summary>
		/// Gets a StringFormat Object for the Given ContentAlignment Object.
		/// </summary>
		/// <param name="textalign">Current ContentAlignment.</param>
		/// <returns>StringFormat that Matches the ContentAlignment.</returns>
        public static StringFormat StringFormatAlignment (ContentAlignment textalign)
        {
            StringFormat sf = new StringFormat();
            switch (textalign)
            {
                case ContentAlignment.TopLeft:
                case ContentAlignment.TopCenter:
                case ContentAlignment.TopRight:
                    sf.LineAlignment = StringAlignment.Near;
                    break;
                case ContentAlignment.MiddleLeft:
                case ContentAlignment.MiddleCenter:
                case ContentAlignment.MiddleRight:
                    sf.LineAlignment = StringAlignment.Center;
                    break;
                case ContentAlignment.BottomLeft:
                case ContentAlignment.BottomCenter:
                case ContentAlignment.BottomRight:
                    sf.LineAlignment = StringAlignment.Far;
                    break;
            }
            switch (textalign)
            {
                case ContentAlignment.TopLeft:
                case ContentAlignment.MiddleLeft:
                case ContentAlignment.BottomLeft:
                    sf.Alignment = StringAlignment.Near;
                    break;
                case ContentAlignment.TopCenter:
                case ContentAlignment.MiddleCenter:
                case ContentAlignment.BottomCenter:
                    sf.Alignment = StringAlignment.Center;
                    break;
                case ContentAlignment.TopRight:
                case ContentAlignment.MiddleRight:
                case ContentAlignment.BottomRight:
                    sf.Alignment = StringAlignment.Far;
                    break;
            }
            return sf;
		}

		/// <summary>
		/// Gets the TD element that was clicked int the given webber.
		/// </summary>
		/// <param name="web">Webber to get TD Element for.</param>
		/// <returns>The needed TD Element.</returns>
		public static HtmlElement GetTDElement (Webber web)
		{
			// Get Cell (TD)...
			HtmlElement elTD = web.GetParentElement(web.ActiveElement, "TD");
			if (elTD == null)
			{
				elTD = web.GetParentElement(web.MouseClickElement, "TD");
				if (elTD == null)
					return null;
			}

			return elTD;
		}

		/// <summary>
		/// Gets the TD element that was clicked int the given webber.
		/// </summary>
		/// <param name="web">Webber to get TD Element for.</param>
		/// <returns>The needed TD Element.</returns>
		public static HtmlElement GetTRElement (Webber web)
		{
			HtmlElement trEl = Common.GetTDElement(web);
			if (trEl != null)
				trEl = web.GetParentElement(trEl, "TR");
			return trEl;
		}
    }
}
